package com.tencent.sr.iris.activity.common.config;

import cn.hutool.core.thread.NamedThreadFactory;
import com.tencent.sr.rmall.springbootstarter.route.TsrExecutorsUtil;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class IrisThreadPoolConfig {

    public static final String IRIS_QUERY_EXECUTOR = "irisQueryExecutor";

    public static final String IRIS_DEFAULT_THREAD_EXECUTOR = "irisDefaultThreadExecutor";

    public static final String IRIS_USER_MSG_TASK_THREAD_EXECUTOR = "irisUserMsgTaskThreadExecutor";

    public static final String IRIS_USER_BATCH_DATA_THREAD_EXECUTOR = "irisUserBatchDataThreadExecutor";

    public static final String IRIS_FRESH_DATA_THREAD_EXECUTOR = "irisFreshDataThreadExecutor";

    public static final String IRIS_AWARD_MONITOR_THREAD_EXECUTOR = "irisAwardMonitorThreadExecutor";

    public static final Integer IRIS_USER_BATCH_DATA_THREAD_COUNT = 8;

    /**
     * 专用线程池
     */
    @Bean(IRIS_QUERY_EXECUTOR)
    public ExecutorService irisQueryExecutor() {
        final String threadName = "irisQueryExecutor";
        return TsrExecutorsUtil.getTtlExecutor(new ThreadPoolExecutor(
                // 核心线程池大小，表示线程池常驻线程数量
                3,
                // 最大线程数，表示线程池最多创建的线程数量
                20,
                // 保活时间，表示一个非核心线程多久没有使用，会被回收
                60,
                TimeUnit.SECONDS,
                // 阻塞队列，表示队列最多缓存多少任务，如果队列满了，将触发RejectedExecutionHandler
                new SynchronousQueue<>(),
                // 线程工厂，创建线程时候用的，可以给线程命名等
                new NamedThreadFactory(threadName, false),
                new ThreadPoolExecutor.CallerRunsPolicy()
        ), threadName);
    }

    /**
     * 消息推送任务线程池
     *
     * @return
     */
    @Bean(IRIS_USER_MSG_TASK_THREAD_EXECUTOR)
    public ExecutorService irisUserMessageTaskExecutor() {
        final String threadName = "irisUserMsgTaskThreadExecutor";
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(15,
                20,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(1000),
                new NamedThreadFactory(threadName, false),
                new ThreadPoolExecutor.CallerRunsPolicy());
        return TsrExecutorsUtil.getTtlExecutor(threadPoolExecutor, threadName);
    }


    /**
     * 异步任务默认线程池
     *
     * @return
     */
    @Bean(IRIS_DEFAULT_THREAD_EXECUTOR)
    public Executor taskExecutor() {
        final String threadName = "irisDefaultThreadExecutor";
        ExecutorService executor = TsrExecutorsUtil.getTtlExecutor(new ThreadPoolExecutor(
                // 核心线程池大小，表示线程池常驻线程数量
                5,
                // 最大线程数，表示线程池最多创建的线程数量
                50,
                // 保活时间，表示一个非核心线程多久没有使用，会被回收
                10,
                TimeUnit.MINUTES,
                // 阻塞队列，表示队列最多缓存多少任务，如果队列满了，将触发RejectedExecutionHandler
                new ArrayBlockingQueue<>(100),
                // 线程工厂，创建线程时候用的，可以给线程命名等
                new NamedThreadFactory(threadName, false),
                new ThreadPoolExecutor.CallerRunsPolicy()
        ), threadName);
        return executor;
    }

    /**
     * 异步任务默认线程池
     *
     * @return
     */
    @Bean(IRIS_USER_BATCH_DATA_THREAD_EXECUTOR)
    public Executor userBatchDataExecutor() {
        final String threadName = "irisUserBatchDataThreadExecutor";
        ExecutorService executor = TsrExecutorsUtil.getTtlExecutor(new ThreadPoolExecutor(
                // 核心线程池大小，表示线程池常驻线程数量
                IRIS_USER_BATCH_DATA_THREAD_COUNT,
                // 最大线程数，表示线程池最多创建的线程数量
                IRIS_USER_BATCH_DATA_THREAD_COUNT,
                // 保活时间，表示一个非核心线程多久没有使用，会被回收
                10,
                TimeUnit.MINUTES,
                // 阻塞队列，表示队列最多缓存多少任务，如果队列满了，将触发RejectedExecutionHandler
                new ArrayBlockingQueue<>(500),
                // 线程工厂，创建线程时候用的，可以给线程命名等
                new NamedThreadFactory(threadName, false),
                new ThreadPoolExecutor.CallerRunsPolicy()
        ), threadName);
        return executor;
    }

    /**
     * 邀请有礼刷数据线程池
     *
     * @return
     */
    @Bean(IRIS_FRESH_DATA_THREAD_EXECUTOR)
    public Executor irisFreshDataThreadExecutor() {
        final String threadName = "irisFreshDataThreadExecutor";
        ExecutorService executor = TsrExecutorsUtil.getTtlExecutor(new ThreadPoolExecutor(
                // 核心线程池大小，表示线程池常驻线程数量
                4,
                // 最大线程数，表示线程池最多创建的线程数量
                4,
                // 保活时间，表示一个非核心线程多久没有使用，会被回收
                10,
                TimeUnit.MINUTES,
                // 阻塞队列，表示队列最多缓存多少任务，如果队列满了，将触发RejectedExecutionHandler
                new SynchronousQueue<>(),
                // 线程工厂，创建线程时候用的，可以给线程命名等
                new NamedThreadFactory(threadName, false),
                new ThreadPoolExecutor.CallerRunsPolicy()
        ), threadName);
        return executor;
    }

    /**
     * 发奖监控线程池
     *
     * @return
     */
    @Bean(IRIS_AWARD_MONITOR_THREAD_EXECUTOR)
    public Executor awardMonitor() {
        final String threadName = "irisAwardMonitorThreadExecutor";
        ExecutorService executor = TsrExecutorsUtil.getTtlExecutor(new ThreadPoolExecutor(
                // 核心线程池大小，表示线程池常驻线程数量
                1,
                // 最大线程数，表示线程池最多创建的线程数量
                1,
                // 保活时间，表示一个非核心线程多久没有使用，会被回收
                60,
                TimeUnit.MINUTES,
                // 阻塞队列，表示队列最多缓存多少任务，如果队列满了，将触发RejectedExecutionHandler
                new SynchronousQueue<>(),
                // 线程工厂，创建线程时候用的，可以给线程命名等
                new NamedThreadFactory(threadName, false),
                new ThreadPoolExecutor.AbortPolicy()
        ), threadName);
        return executor;
    }

}
